﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace FirstFloor.Documents.Extensions
{
    /// <summary>
    /// Provides IObservable extensions
    /// </summary>
    public static class ObservableExtensions
    {
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="R"></typeparam>
        /// <param name="that">The that.</param>
        /// <param name="keySelector">The key selector.</param>
        /// <returns></returns>
        public static IObservable<T> OrderBy<T, R>(this IObservable<T> that, Func<T, R> keySelector)
        {
            return new AnonymousObservable<T>(
                observer => {
                    var orderBySubject = new OrderBySubject<T, R>(keySelector);
                    var unsubscribe = orderBySubject.Subscribe(observer);
                    that.Subscribe(orderBySubject);

                    return unsubscribe;
                });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="R"></typeparam>
        public class OrderBySubject<T, R> : Subject<T>
        {
            private Func<T, R> keySelector { get; set; }

            /// <summary>
            /// Initializes a new instance of the <see cref="OrderBySubject&lt;T, R&gt;"/> class.
            /// </summary>
            /// <param name="keySelector">The key selector.</param>
            public OrderBySubject(Func<T, R> keySelector)
            {
                this.keySelector = keySelector;
            }
            List<T> list = new List<T>();
            /// <summary>
            /// Called when [next].
            /// </summary>
            /// <param name="value">The value.</param>
            public override void OnNext(T value)
            {
                list.Add(value);
            }
            /// <summary>
            /// Called when completed.
            /// </summary>
            public override void OnCompleted()
            {
                foreach (var item in list.OrderBy(keySelector)) {
                    base.OnNext(item);
                    base.OnCompleted();
                }
            }
        }
    }
}
